package org.lisen.scdemo.sender.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

/**
 * @author Administrator
 * @create 2020-02-2821:00
 */
@Configuration
@Slf4j
public class RabbitTemplateConfig {

    @Bean
    public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);

        //消息发送失败返回队列，publisher-returns:true
        template.setMandatory(true);

        template.setMessageConverter(new Jackson2JsonMessageConverter());
        template.setEncoding("utf-8");

        //实现消息发送到exchange后接收ack回调,publisher-confirms:true
        //如果队列是可持久化的，则在消息成功持久化之后生产者收到确认消息
        template.setConfirmCallback(((correlationData, ack, cause) -> {
            if(ack) {
                log.info("消息成功发送到exchange，id:{}", correlationData.getId());
            } else {
                /*
                 * 消息未被投放到对应的消费者队列，可能的原因：
                 * 1）发送时在未找到exchange，例如exchange参数书写错误
                 * 2）消息队列已达最大长度限制（声明队列时可配置队列的最大限制），此时
                 * 返回的cause为null。
                 */
                log.info("******************************************************");
                log.info("11消息发送失败: {}", cause);
            }
        }));

        //实现消息发送的exchange，但没有相应的队列于交换机绑定时的回调
        template.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            String id = message.getMessageProperties().getCorrelationId();
            log.info("消息：{} 发送失败, 应答码：{} 原因：{} 交换机: {}  路由键: {}", id, replyCode, replyText, exchange, routingKey);
        });

        return template;
    }

}
